home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / games / nhak_src.zip / DBRIDGE.C < prev    next >
C/C++ Source or Header  |  1993-03-16  |  22KB  |  924 lines

  1. /*     SCCS Id: @(#)dbridge.c  3.0     88/18/12
  2. /*     Copyright (c) 1989 by Jean-Christophe Collet */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. /*
  6.  * This file contains the drawbridge manipulation (create, open, close,
  7.  * destroy).
  8.  *
  9.  * Added comprehensive monster-handling, and the "entity" structure to 
  10.  * deal with players as well. - 11/89
  11.  */
  12.  
  13. #include "hack.h"
  14.  
  15. #ifdef STRONGHOLD
  16. # ifdef OVLB
  17. static void FDECL(redosym, (int, int));
  18. static void FDECL(get_wall_for_db, (int *, int *));
  19. static struct entity *FDECL(e_at, (int, int));
  20. static void FDECL(m_to_e, (struct monst *, struct entity *));
  21. static void FDECL(u_to_e, (struct entity *));
  22. static void FDECL(set_entity, (int, int, struct entity *));
  23. static char *FDECL(e_nam, (struct entity *));
  24. /* static char *FDECL(Enam, (struct entity *)); */ /* unused */
  25. static char *FDECL(E_phrase, (struct entity *, const char *));
  26. static boolean FDECL(e_survives_at, (struct entity *, int, int));
  27. static void FDECL(e_died, (struct entity *, int, int));
  28. static boolean FDECL(automiss, (struct entity *));
  29. static boolean FDECL(e_missed, (struct entity *, BOOLEAN_P));
  30. static boolean FDECL(e_jumps, (struct entity *));
  31. static void FDECL(do_entity, (struct entity *));
  32. # endif /* OVLB */
  33. #endif /* STRONGHOLD */
  34.  
  35. #ifdef OVL0
  36.  
  37. boolean
  38. is_pool(x,y)
  39. int x,y;
  40. {
  41.        if(levl[x][y].typ == POOL || levl[x][y].typ == MOAT) return TRUE;
  42. #ifdef STRONGHOLD
  43.        if(levl[x][y].typ == DRAWBRIDGE_UP &&
  44.                (levl[x][y].drawbridgemask & DB_UNDER) == DB_MOAT) return TRUE;
  45. #endif
  46.        return FALSE;
  47. }
  48.  
  49. #endif /* OVL0 */
  50.  
  51. #ifdef STRONGHOLD
  52.  
  53. #ifdef OVL1
  54.  
  55. void
  56. initsym(x,y)
  57. int x,y;
  58. {
  59.     char oldseen;
  60.     struct rm *crm = &levl[x][y];
  61.  
  62.     oldseen = crm->seen;
  63.     crm->seen = 1;
  64.     crm->scrsym = news0(x,y);
  65.     crm->seen = oldseen;
  66. }
  67.  
  68. #endif /* OVL1 */
  69. #ifdef OVLB
  70.  
  71. static void
  72. redosym(x,y)
  73. int x,y;
  74. {
  75.     if(cansee(x,y)) {
  76.         levl[x][y].seen = 0;            /* force prl */
  77.         prl(x, y);
  78.     } else {
  79.         initsym(x,y);
  80.         levl[x][y].seen = 0;
  81.     }
  82. }
  83.  
  84. #endif /* OVLB */
  85. #ifdef OVL1
  86.  
  87. /* 
  88.  * We want to know whether a wall (or a door) is the portcullis (passageway)
  89.  * of an eventual drawbridge.
  90.  *
  91.  * Return value:  the direction of the drawbridge.
  92.  */
  93.  
  94. int
  95. is_drawbridge_wall(x,y)
  96. int x,y;
  97. {
  98.     struct rm *lev;
  99.  
  100.     lev = &levl[x][y];
  101.     if (lev->typ != DOOR && !(lev->diggable & W_GATEWAY))
  102.         return (-1);
  103.     switch (lev->typ) {
  104.     case DOOR:
  105.     case VWALL:
  106.         if (IS_DRAWBRIDGE(levl[x+1][y].typ) &&
  107.              (levl[x+1][y].drawbridgemask & DB_DIR) == DB_WEST)
  108.             return (DB_WEST);
  109.         if (IS_DRAWBRIDGE(levl[x-1][y].typ) && 
  110.             (levl[x-1][y].drawbridgemask & DB_DIR) == DB_EAST)
  111.             return (DB_EAST);
  112.         if (lev->typ == VWALL) break;
  113.     case HWALL:
  114.         if (IS_DRAWBRIDGE(levl[x][y-1].typ) && 
  115.             (levl[x][y-1].drawbridgemask & DB_DIR) == DB_SOUTH)
  116.             return (DB_SOUTH);
  117.         if (IS_DRAWBRIDGE(levl[x][y+1].typ) && 
  118.             (levl[x][y+1].drawbridgemask & DB_DIR) == DB_NORTH)
  119.             return (DB_NORTH);
  120.     }
  121.     return (-1);
  122. }
  123.  
  124. /*
  125.  * Use is_db_wall where you want to verify that a
  126.  * drawbridge "wall" is UP in the location x, y
  127.  * (instead of UP or DOWN, as with is_drawbridge_wall). 
  128.  */ 
  129. boolean
  130. is_db_wall(x,y)
  131. int x,y;
  132. {
  133.     return( (levl[x][y].typ == VWALL || levl[x][y].typ == HWALL) &&
  134.         levl[x][y].diggable & W_GATEWAY);
  135. }
  136.  
  137.  
  138. /*
  139.  * Return true with x,y pointing to the drawbridge if x,y initially indicate
  140.  * a drawbridge or drawbridge wall.
  141.  */
  142. boolean
  143. find_drawbridge(x,y)
  144. int *x,*y;
  145. {
  146.     int dir;
  147.  
  148.     if (IS_DRAWBRIDGE(levl[*x][*y].typ))
  149.         return TRUE;
  150.     dir = is_drawbridge_wall(*x,*y);
  151.     if (dir >= 0) {
  152.         switch(dir) {
  153.             case DB_NORTH: (*y)++; break;
  154.             case DB_SOUTH: (*y)--; break;
  155.             case DB_EAST:  (*x)--; break;
  156.             case DB_WEST:  (*x)++; break;
  157.         }
  158.         return TRUE;
  159.     }
  160.     return FALSE;
  161. }
  162.  
  163. #endif /* OVL1 */
  164. #ifdef OVLB
  165.  
  166. /* 
  167.  * Find the drawbridge wall associated with a drawbridge.
  168.  */
  169. static void
  170. get_wall_for_db(x,y)
  171. int *x,*y;
  172. {
  173.     switch (levl[*x][*y].drawbridgemask & DB_DIR) {
  174.         case DB_NORTH: (*y)--; break;
  175.         case DB_SOUTH: (*y)++; break;
  176.         case DB_EAST:  (*x)++; break;
  177.         case DB_WEST:  (*x)--; break;
  178.     }
  179. }
  180.  
  181. /*
  182.  * Creation of a drawbridge at pos x,y.
  183.  *     dir is the direction.
  184.  *     flag must be put to TRUE if we want the drawbridge to be opened.
  185.  */
  186.  
  187. boolean
  188. create_drawbridge(x,y,dir,flag)
  189. int x,y,dir;
  190. boolean flag;
  191. {
  192.     int x2,y2;
  193.     uchar wall;
  194.  
  195.     x2 = x; y2 = y;
  196.     switch(dir) {
  197.         case DB_NORTH:
  198.             wall = HWALL;
  199.             y2--;
  200.             break;
  201.         case DB_SOUTH:
  202.             wall = HWALL;
  203.             y2++;
  204.             break;
  205.         case DB_EAST:
  206.             wall = VWALL;
  207.             x2++;
  208.             break;
  209.         default:
  210.             impossible("bad direction in create_drawbridge");
  211.             /* fall through */
  212.         case DB_WEST:
  213.             wall = VWALL;
  214.             x2--;
  215.             break;
  216.     }
  217.     if (!IS_WALL(levl[x2][y2].typ))
  218.         return(FALSE);
  219.     if (flag) {             /* We want the bridge open */
  220.         levl[x][y].typ = DRAWBRIDGE_DOWN;
  221.         levl[x2][y2].typ = DOOR;
  222.         levl[x2][y2].doormask = D_NODOOR;
  223.     } else {
  224.         levl[x][y].typ = DRAWBRIDGE_UP;
  225.         levl[x2][y2].typ = wall;
  226.         /* Beware, drawbridges are non-diggable. */
  227.         levl[x2][y2].diggable = (W_NONDIGGABLE | W_GATEWAY);
  228.     }
  229.     levl[x][y].drawbridgemask = dir;        /* always have DB_MOAT */
  230.     initsym(x,y);
  231.     initsym(x2,y2);
  232.     return(TRUE);           
  233. }
  234.  
  235. struct entity {
  236.     struct monst *emon;       /* youmonst for the player */
  237.     struct permonst *edata;    /* must be non-zero for record to be valid */
  238.     int ex, ey;
  239. };
  240.  
  241. #define ENTITIES 2
  242.  
  243. static struct entity NEARDATA occupants[ENTITIES];
  244.  
  245. static
  246. struct entity *
  247. e_at(x, y)
  248. int x, y;
  249. {
  250.     int entitycnt;
  251.     
  252.     for (entitycnt = 0; entitycnt < ENTITIES; entitycnt++)
  253.         if ((occupants[entitycnt].edata) && 
  254.             (occupants[entitycnt].ex == x) &&
  255.             (occupants[entitycnt].ey == y))
  256.             break;
  257. #ifdef D_DEBUG
  258.     pline("entitycnt = %d", entitycnt);
  259.     fflush(stdout);
  260. #endif
  261.     return((entitycnt == ENTITIES)? 
  262.            (struct entity *)0 : &(occupants[entitycnt]));
  263. }
  264.  
  265. static void
  266. m_to_e(mtmp, etmp)
  267. struct monst *mtmp;
  268. struct entity *etmp;
  269. {
  270.     etmp->emon = mtmp;
  271.     if (mtmp) {
  272.         etmp->ex = mtmp->mx;
  273.         etmp->ey = mtmp->my;
  274.         etmp->edata = mtmp->data;
  275.     } else
  276.         etmp->edata = (struct permonst *)0;
  277. }
  278.  
  279. static void
  280. u_to_e(etmp)
  281. struct entity *etmp;
  282. {
  283.     etmp->emon = &youmonst;
  284.     etmp->ex = u.ux;
  285.     etmp->ey = u.uy;
  286.     etmp->edata = uasmon;
  287. }
  288.  
  289. static void
  290. set_entity(x, y, etmp)
  291. int x, y;
  292. struct entity *etmp;
  293. {
  294.     if ((x == u.ux) && (y == u.uy))
  295.         u_to_e(etmp);
  296.     else
  297.         if (MON_AT(x, y))
  298.             m_to_e(m_at(x, y), etmp);
  299.         else
  300.             etmp->edata = (struct permonst *)0;
  301. }
  302.  
  303. #ifdef POLYSELF
  304. #define is_u(etmp) (etmp->emon == &youmonst)
  305. #else
  306. #define is_u(x) FALSE
  307. #endif
  308.  
  309. /* 
  310.  * WARNING! THE FOLLOWING IS ONLY USEFUL FOR CANSEEMON, OR OTHER FUNCS WHICH 
  311.  * ALWAYS RETURN TRUE FOR U.
  312.  */
  313.  
  314. #define e_boolean(etmp, func) (is_u(etmp)? (boolean)TRUE : func(etmp->emon)) 
  315.  
  316. /*
  317.  * e_strg is a utility routine which is not actually in use anywhere, since 
  318.  * the specialized routines below suffice for all current purposes. 
  319.  */
  320.  
  321. /* #define e_strg(etmp, func) (is_u(etmp)? (char *)0 : func(etmp->emon)) */
  322.  
  323. static char *
  324. e_nam(etmp)
  325. struct entity *etmp;
  326. {
  327.     return(is_u(etmp)? "you" : mon_nam(etmp->emon));
  328. }
  329.  
  330. /*
  331.  * Enam is another unused utility routine:  E_phrase is preferable.
  332.  */
  333.  
  334. /*
  335. static char *
  336. Enam(etmp)
  337. struct entity *etmp;
  338. {
  339.     return(is_u(etmp)? "You" : Monnam(etmp->emon));
  340. }
  341. */
  342.  
  343. /*
  344.  * Generates capitalized entity name, makes 2nd -> 3rd person conversion on 
  345.  * verb, where necessary.
  346.  */
  347.  
  348. static char *
  349. E_phrase(etmp, verb)
  350. struct entity *etmp;
  351. const char *verb;
  352. {
  353.     char wholebuf[80], verbbuf[30];
  354.  
  355.     if (is_u(etmp)) 
  356.         Strcpy(wholebuf, "You");
  357.     else
  358.         Strcpy(wholebuf, Monnam(etmp->emon));
  359.     if (!*verb)
  360.         return(wholebuf);
  361.     Strcat(wholebuf, " ");
  362.     verbbuf[0] = '\0';
  363.     if (is_u(etmp)) 
  364.         Strcpy(verbbuf, verb);
  365.     else {
  366.         if (!strcmp(verb, "are"))
  367.             Strcpy(verbbuf, "is");
  368.         if (!strcmp(verb, "have"))
  369.             Strcpy(verbbuf, "has");
  370.         if (!verbbuf[0]) {
  371.             Strcpy(verbbuf, verb);
  372.             switch (verbbuf[strlen(verbbuf) - 1]) {
  373.                 case 'y':
  374.                     verbbuf[strlen(verbbuf) - 1] = '\0';
  375.                     Strcat(verbbuf, "ies");
  376.                     break;
  377.                 case 'h':
  378.                 case 'o':
  379.                 case 's':
  380.                     Strcat(verbbuf, "es");
  381.                     break;
  382.                 default:
  383.                     Strcat(verbbuf, "s");
  384.                     break;
  385.             }
  386.         }
  387.     }
  388.     Strcat(wholebuf, verbbuf);
  389.     return(wholebuf);
  390. }
  391.  
  392. /*
  393.  * Simple-minded "can it be here?" routine
  394.  */
  395.  
  396. static boolean
  397. e_survives_at(etmp, x, y)
  398. struct entity *etmp;
  399. int x, y;
  400. {
  401.     if (noncorporeal(etmp->edata))
  402.         return(TRUE);
  403.     if (is_pool(x, y))
  404.         return((is_u(etmp) && (Wwalking || Levitation)) ||
  405.                is_swimmer(etmp->edata) || is_flyer(etmp->edata) ||
  406.                is_floater(etmp->edata));
  407.     if (is_db_wall(x, y))
  408.         return(passes_walls(etmp->edata));
  409.     return(TRUE);
  410. }
  411.  
  412. static void
  413. e_died(etmp, dest, how)
  414. struct entity *etmp;
  415. int dest, how;
  416. {
  417.     if (is_u(etmp)) {
  418.         if (how == DROWNING)
  419.             drown();
  420.         else {
  421.             coord xy;
  422.  
  423.             killer_format = KILLED_BY_AN;
  424.             killer = "falling drawbridge";
  425.             done(how);
  426.             /* So, you didn't die */
  427.             if (!e_survives_at(etmp, etmp->ex, etmp->ey)) {
  428.                 pline("A %s force teleports you away...",
  429.                             Hallucination ? "normal" : "strange");
  430.                 (void) enexto(&xy, etmp->ex, etmp->ey,
  431.                                 etmp->edata);
  432.                 teleds(xy.x, xy.y);
  433.             }
  434.         }
  435.     } else {
  436.         xkilled(etmp->emon, dest);
  437.         etmp->edata = (struct permonst *)0;    
  438.     }
  439. }
  440.  
  441.  
  442. /*
  443.  * These are never directly affected by a bridge or portcullis.
  444.  */
  445.  
  446. static boolean
  447. automiss(etmp)
  448. struct entity *etmp;
  449. {
  450.     return(passes_walls(etmp->edata) || noncorporeal(etmp->edata));
  451. }
  452.  
  453. /*
  454.  * Does falling drawbridge or portcullis miss etmp?
  455.  */
  456.  
  457. static boolean
  458. e_missed(etmp, chunks)
  459. struct entity *etmp;
  460. boolean chunks;
  461. {
  462.     int misses;
  463.  
  464. #ifdef D_DEBUG
  465.     if (chunks)
  466.         pline("Do chunks miss?");
  467. #endif
  468.     if (automiss(etmp))
  469.         return(TRUE);    
  470.  
  471.     if (is_flyer(etmp->edata) && 
  472.         (is_u(etmp)? !Sleeping : 
  473.          (etmp->emon->mcanmove && !etmp->emon->msleep)))
  474.                           /* flying requires mobility */
  475.         misses = 5;    /* out of 8 */    
  476.     else
  477.         if (is_floater(etmp->edata) ||
  478.             (is_u(etmp) && Levitation))      /* doesn't require mobility */
  479.             misses = 3;
  480.         else
  481.             if (chunks && is_pool(etmp->ex, etmp->ey))
  482.                 misses = 2;              /* sitting ducks */
  483.             else
  484.                 misses = 0;      
  485.  
  486.     if (is_db_wall(etmp->ex, etmp->ey))
  487.         misses -= 3;                     /* less airspace */
  488.  
  489. #ifdef D_DEBUG
  490.     pline("Miss chance = %d (out of 8)", misses);
  491. #endif
  492.  
  493.     return((misses >= rnd(8))? TRUE : FALSE);
  494. }
  495.  
  496. /*
  497.  * Can etmp jump from death?
  498.  */ 
  499.  
  500. static boolean
  501. e_jumps(etmp)
  502. struct entity *etmp;
  503. {
  504.     int tmp = 4;         /* out of 10 */
  505.  
  506.     if (is_u(etmp)? (Sleeping || Fumbling) : 
  507.                 (!etmp->emon->mcanmove || etmp->emon->msleep || 
  508.              !etmp->edata->mmove))
  509.         return(FALSE);
  510.  
  511.     if (is_u(etmp)? Confusion : etmp->emon->mconf)
  512.         tmp -= 2;
  513.  
  514.     if (is_u(etmp)? Stunned : etmp->emon->mstun)
  515.         tmp -= 3;
  516.  
  517.     if (is_db_wall(etmp->ex, etmp->ey))
  518.         tmp -= 2;                 /* less room to maneuver */
  519.     
  520. #ifdef D_DEBUG
  521.     pline("%s to jump (%d chances in 10)", E_phrase(etmp, "try"), tmp);
  522. #endif
  523.     return((tmp >= rnd(10))? TRUE : FALSE);
  524. }
  525.  
  526. static void
  527. do_entity(etmp)
  528. struct entity *etmp;
  529. {
  530.     int newx, newy, at_portcullis, oldx, oldy;
  531.     boolean must_jump = FALSE, relocates = FALSE, e_inview;
  532.     struct rm *crm;
  533.  
  534.     if (!etmp->edata)
  535.         return;
  536.  
  537.     e_inview = e_boolean(etmp, canseemon);
  538.  
  539.     oldx = etmp->ex;
  540.     oldy = etmp->ey;
  541.  
  542.     at_portcullis = is_db_wall(oldx, oldy);
  543.  
  544.     crm = &levl[oldx][oldy];
  545.  
  546.     if (automiss(etmp) && e_survives_at(etmp, oldx, oldy)) {
  547.         char edifice[20];
  548.  
  549.         if (e_inview) {
  550.             *edifice = '\0';
  551.             if ((crm->typ == DRAWBRIDGE_DOWN) ||
  552.                     (crm->typ == DRAWBRIDGE_UP))
  553.                 Strcpy(edifice, "drawbridge");
  554.             else
  555.                      if (at_portcullis) 
  556.                     Strcpy(edifice, "portcullis");
  557.             if (*edifice)
  558.                 pline("The %s passes through %s!", edifice, 
  559.                             e_nam(etmp));            
  560.         }
  561.         return;
  562.     }
  563.     if (e_missed(etmp, FALSE)) { 
  564.         if (at_portcullis)
  565.             pline("The portcullis misses %s!",
  566.                   e_nam(etmp));
  567. #ifdef D_DEBUG
  568.         else
  569.             pline("The drawbridge misses %s!", 
  570.                   e_nam(etmp));
  571. #endif
  572.         if (e_survives_at(etmp, oldx, oldy)) 
  573.             return;
  574.         else {
  575. #ifdef D_DEBUG
  576.             pline("Mon can't survive here");
  577. #endif
  578.             if (at_portcullis)
  579.                 must_jump = TRUE;
  580.             else
  581.                 relocates = TRUE;  /* just ride drawbridge in */
  582.         }
  583.     } else {
  584.         if (crm->typ == DRAWBRIDGE_DOWN) {
  585.             pline("%s crushed underneath the drawbridge.",
  586.                         E_phrase(etmp, "are"));              /* no jump */
  587.             e_died(etmp, e_inview? 2 : 3, CRUSHING); /* no corpse */
  588.             return;   /* Note: Beyond this point, we know we're   */
  589.         }                 /* not at an opened drawbridge, since all   */
  590.         must_jump = TRUE; /* *missable* creatures survive on the      */
  591.     }              /* square, and all the unmissed ones die.   */
  592.     if (must_jump) 
  593.         if (at_portcullis) {
  594.             if (e_jumps(etmp)) {
  595.                 relocates = TRUE;
  596. #ifdef D_DEBUG
  597.                 pline("Jump succeeds!");
  598. #endif
  599.             } else {
  600.                 if (e_inview)
  601.                    pline("%s crushed by the falling portcullis!",
  602.                                  E_phrase(etmp, "are"));
  603.                 else
  604.                     if (flags.soundok)
  605.                         You("hear a crushing sound.");
  606.                 e_died(etmp, e_inview? 1 : 0, CRUSHING);
  607.                                     /* corpse */
  608.                 return;
  609.             }
  610.         } else {       /* tries to jump off bridge to original square */
  611.             relocates = !e_jumps(etmp); 
  612. #ifdef D_DEBUG
  613.             pline("Jump %s!", (relocates)? "fails" : "succeeds");
  614. #endif
  615.         }
  616.  
  617. /*
  618.  * Here's where we try to do relocation.  Assumes that etmp is not arriving
  619.  * at the portcullis square while the drawbridge is falling, since this square
  620.  * would be inaccessible (i.e. etmp started on drawbridge square) or 
  621.  * unnecessary (i.e. etmp started here) in such a situation.
  622.  */
  623. #ifdef D_DEBUG
  624.     pline("Doing relocation");
  625. #endif
  626.     newx = oldx;
  627.     newy = oldy;
  628.     (void)find_drawbridge(&newx, &newy);
  629.     if ((newx == oldx) && (newy == oldy))
  630.         get_wall_for_db(&newx, &newy);
  631. #ifdef D_DEBUG
  632.     pline("Checking new square for occupancy");
  633. #endif
  634.     if (relocates && (e_at(newx, newy))) { 
  635.  
  636. /* 
  637.  * Standoff problem:  one or both entities must die, and/or both switch 
  638.  * places.  Avoid infinite recursion by checking first whether the other 
  639.  * entity is staying put.  Clean up if we happen to move/die in recursion.
  640.  */
  641.         struct entity *other;
  642.  
  643.         other = e_at(newx, newy);
  644. #ifdef D_DEBUG
  645.         pline("New square is occupied by %s", e_nam(other));
  646. #endif
  647.         if (e_survives_at(other, newx, newy) && automiss(other)) {
  648.             relocates = FALSE;                /* "other" won't budge */
  649. #ifdef D_DEBUG
  650.             pline("%s suicide.", E_phrase(etmp, "commit"));
  651. #endif
  652.         } else {
  653.  
  654. #ifdef D_DEBUG
  655.             pline("Handling %s", e_nam(other));
  656. #endif
  657.             while ((e_at(newx, newy)) && 
  658.                    (e_at(newx, newy) != etmp))
  659.                        do_entity(other);
  660. #ifdef D_DEBUG
  661.             pline("Checking existence of %s", 
  662.                   e_nam(etmp));
  663.             fflush(stdout);
  664. #endif
  665.             if (e_at(oldx, oldy) != etmp) {
  666. #ifdef D_DEBUG
  667.                     pline("%s moved or died in recursion somewhere",
  668.                       E_phrase(etmp, "have"));
  669.                 fflush(stdout);
  670. #endif
  671.                 return;
  672.             }
  673.         }
  674.     }
  675.     if (relocates) {
  676. #ifdef D_DEBUG
  677.         pline("Moving %s", e_nam(etmp));
  678. #endif
  679.         if (!is_u(etmp)) {
  680.             remove_monster(etmp->ex, etmp->ey);
  681.             place_monster(etmp->emon, newx, newy);
  682.         } else {
  683.             u.ux = newx;
  684.             u.uy = newy;
  685.         }
  686.         etmp->ex = newx;
  687.         etmp->ey = newy;
  688.         e_inview = e_boolean(etmp, canseemon);
  689.     }
  690. #ifdef D_DEBUG
  691.     pline("Final disposition of %s", e_nam(etmp));
  692.     fflush(stdout);
  693. #endif
  694.     if (is_db_wall(etmp->ex, etmp->ey)) {
  695. #ifdef D_DEBUG
  696.         pline("%s in portcullis chamber", E_phrase(etmp, "are"));
  697.         fflush(stdout);
  698. #endif
  699.         if (e_inview)
  700.             if (is_u(etmp)) {
  701.                 You("tumble towards the closed portcullis!"); 
  702.                 if (automiss(etmp))
  703.                     You("pass through it!");
  704.                 else
  705.                     pline("The drawbridge closes in...");
  706.             } else
  707.                 pline("%s behind the drawbridge.",
  708.                                   E_phrase(etmp, "disappear"));
  709.         if (!e_survives_at(etmp, etmp->ex, etmp->ey)) {
  710.             killer_format = KILLED_BY_AN;
  711.             killer = "closing drawbridge";
  712.             e_died(etmp, 0, CRUSHING);         /* no message */
  713.             return;
  714.         }
  715. #ifdef D_DEBUG
  716.         pline("%s in here", E_phrase(etmp, "survive"));
  717. #endif
  718.     } else {
  719. #ifdef D_DEBUG
  720.         pline("%s on drawbridge square", E_phrase(etmp, "are"));
  721. #endif
  722.         if (is_pool(etmp->ex, etmp->ey) && !e_inview)
  723.             if (flags.soundok)
  724.                 You("hear a splash.");
  725.         if (e_survives_at(etmp, etmp->ex, etmp->ey)) {
  726.             if (e_inview && !is_flyer(etmp->edata) &&
  727.                 !is_floater(etmp->edata))
  728.                 pline("%s from the bridge.",
  729.                                   E_phrase(etmp, "fall"));    
  730.             return;    
  731.         }
  732. #ifdef D_DEBUG
  733.         pline("%s cannot survive on the drawbridge square", Enam(etmp));
  734. #endif
  735.         if (is_pool(etmp->ex, etmp->ey))
  736.             if (e_inview && 
  737.                 !is_u(etmp))  /* drown() will supply msgs if nec. */
  738.                 if (Hallucination)
  739.                       pline("%s the moat and disappears.",
  740.                         E_phrase(etmp, "drink"));
  741.                 else
  742.                       pline("%s into the moat.",
  743.                                   E_phrase(etmp, "fall"));
  744.         killer_format = NO_KILLER_PREFIX;
  745.         killer = "fell from a drawbridge";
  746.         e_died(etmp, e_inview? 1 : 0,        /* CRUSHING is arbitrary */
  747.                (is_pool(etmp->ex, etmp->ey))? DROWNING : CRUSHING);
  748.                                            /* corpse */
  749.         return;
  750.     }
  751. }
  752.  
  753. /*
  754.  * Close the drawbridge located at x,y
  755.  */
  756.  
  757. void
  758. close_drawbridge(x,y)
  759. int x,y;
  760. {
  761.     register struct rm *lev1, *lev2;
  762.     struct obj *otmp, *otmp2;
  763.     int x2, y2;
  764.  
  765.     lev1 = &levl[x][y];
  766.     if (lev1->typ != DRAWBRIDGE_DOWN) return;
  767.     x2 = x; y2 = y;
  768.     get_wall_for_db(&x2,&y2);
  769.     if (cansee(x,y))   /* change msgs if you are a w-walker at portcullis */
  770.         You("see a drawbridge %s up!", 
  771.             ((u.ux == x2) && (u.uy == y2))? "coming" : "going");
  772.     lev1->typ = DRAWBRIDGE_UP;
  773.     lev2 = &levl[x2][y2];
  774.     switch (lev1->drawbridgemask & DB_DIR) {
  775.         case DB_NORTH:
  776.         case DB_SOUTH:
  777.             lev2->typ = HWALL;
  778.             break;
  779.         case DB_WEST:
  780.         case DB_EAST:
  781.             lev2->typ = VWALL;
  782.             break;
  783.     }
  784.     lev2->diggable = (W_NONDIGGABLE | W_GATEWAY);
  785.     set_entity(x, y, &(occupants[0]));
  786.     set_entity(x2, y2, &(occupants[1]));
  787.     do_entity(&(occupants[0]));
  788.     do_entity(&(occupants[1]));
  789.     redosym(x, y);
  790.     for (otmp = level.objects[x][y]; otmp; otmp = otmp2) {
  791.         otmp2 = otmp->nexthere;
  792.         delobj(otmp);
  793.     }
  794.     for (otmp = level.objects[x2][y2]; otmp; otmp = otmp2) {
  795.         otmp2 = otmp->nexthere;
  796.         delobj(otmp);
  797.     }
  798.     redosym(x2, y2);
  799. }
  800.  
  801. /* 
  802.  * Open the drawbridge located at x,y
  803.  */
  804.  
  805. void
  806. open_drawbridge(x,y)
  807. int x,y;
  808. {
  809.     register struct rm *lev1, *lev2;
  810.     int x2, y2;
  811.  
  812.     lev1 = &levl[x][y];
  813.     if (lev1->typ != DRAWBRIDGE_UP) return;
  814.     x2 = x; y2 = y;
  815.     get_wall_for_db(&x2,&y2);
  816.     if (cansee(x,y))   /* change msgs if you are a w-walker at portcullis */
  817.         You("see a drawbridge %s down!",
  818.             ((x2 == u.ux) && (y2 == u.uy))? "going" : "coming");
  819.     lev1->typ = DRAWBRIDGE_DOWN;
  820.     lev2 = &levl[x2][y2];
  821.     lev2->typ = DOOR;
  822.     lev2->doormask = D_NODOOR;
  823.     set_entity(x, y, &(occupants[0]));
  824.     set_entity(x2, y2, &(occupants[1]));
  825.     do_entity(&(occupants[0]));
  826.     do_entity(&(occupants[1]));
  827.     redosym(x, y);
  828.     redosym(x2, y2);
  829. }
  830.  
  831. /*
  832.  * Let's destroy the drawbridge located at x,y
  833.  */
  834.  
  835. void
  836. destroy_drawbridge(x,y)
  837. int x,y;
  838. {
  839.     register struct rm *lev1, *lev2;
  840.     int x2, y2;
  841.     boolean e_inview;
  842.     struct entity *etmp1 = &(occupants[0]), *etmp2 = &(occupants[1]);
  843.  
  844.     lev1 = &levl[x][y];
  845.     if (!IS_DRAWBRIDGE(lev1->typ))
  846.         return;
  847.     x2 = x; y2 = y;
  848.     get_wall_for_db(&x2,&y2);
  849.     lev2 = &levl[x2][y2];
  850.     if ((lev1->drawbridgemask & DB_UNDER) == DB_MOAT) {
  851.         if (lev1->typ == DRAWBRIDGE_UP) {
  852.             if (cansee(x2,y2))
  853.         pline("The portcullis of the drawbridge falls into the moat!");
  854.             else if (flags.soundok)
  855.                 You("hear a loud *SPLASH*!");
  856.         } else {
  857.             if (cansee(x,y))
  858.                 pline("The drawbridge collapses into the moat!");
  859.             else if (flags.soundok)
  860.                 You("hear a loud *SPLASH*!");
  861.         }
  862.         lev1->typ = MOAT;
  863.         lev1->drawbridgemask = 0;
  864.     } else {
  865.         if (cansee(x,y))
  866.             pline("The drawbridge disintegrates!");
  867.         else
  868.             You("hear a loud *CRASH*!");
  869.         lev1->typ = ROOM;
  870.         lev1->icedpool =
  871.             ((lev1->drawbridgemask & DB_ICE) ? ICED_MOAT : 0);
  872.     }
  873.     set_entity(x2, y2, etmp2); /* currently, only automissers can be here */
  874.     if (etmp2->edata) {
  875.         e_inview = e_boolean(etmp2, canseemon);
  876.         if (!automiss(etmp2)) {               /* i.e. no-one yet */
  877.             if (e_inview)
  878.                 pline("%s blown apart by flying debris",
  879.                             E_phrase(etmp2, "are"));
  880.             killer_format = KILLED_BY_AN;
  881.             killer = "exploding drawbridge";
  882.             e_died(etmp2, e_inview? 2 : 3, CRUSHING);/* no corpse */
  883.         }          /* nothing which is vulnerable can survive this */
  884.     }
  885.     lev2->typ = DOOR;
  886.     lev2->doormask = D_NODOOR;
  887.     set_entity(x, y, etmp1);
  888.     if (etmp1->edata) {
  889.         e_inview = e_boolean(etmp1, canseemon);
  890.         if (e_missed(etmp1, TRUE)) {
  891. #ifdef D_DEBUG
  892.             pline("%s spared!", E_phrase(etmp1, "are"));
  893. #endif
  894.         } else {
  895.             if (e_inview) 
  896.                 if (!is_u(etmp1) && Hallucination)
  897.                     pline("%s into some heavy metal",
  898.                           E_phrase(etmp1, "get"));
  899.                 else
  900.                     pline("%s hit by a huge chunk of metal!",
  901.                                 E_phrase(etmp1, "are"));
  902.             else 
  903.                 if (flags.soundok && !is_u(etmp1) && 
  904.                     !is_pool(x, y))
  905.                     You("hear a crushing sound");
  906. #ifdef D_DEBUG
  907.                 else
  908.                     pline("%s from shrapnel", 
  909.                           E_phrase(etmp1, "die"));
  910. #endif
  911.             killer_format = KILLED_BY_AN;
  912.             killer = "collapsing drawbridge";
  913.             e_died(etmp1, e_inview? 0 : 1, CRUSHING);   /* corpse */
  914.         }
  915.     }
  916.     redosym(x,y);
  917.     redosym(x2,y2);
  918. }
  919.  
  920.  
  921. #endif /* OVLB */
  922.  
  923. #endif /* STRONGHOLD /**/
  924.